/**
 * @author Luc Yriarte
 * 
 * Licence : BSD http://www.opensource.org/licenses/bsd-license.php
 *  
 */
package basicSim;
/* Java 2
import java.util.ArrayList;
import java.util.StringTokenizer;
*/
/**
 * Mesh wireframe model. Edges are represented by the indexes of both ends
 * in the vertex table.
 */
public class Mesh {
	public int nVertex, nEdge;
	/** vertex table */
	protected Vector3D[] vertex;
	/** an edge is a pair of indexes in the vertex table */
	protected int[][] edge;
	/** wireframe lines */
//	protected int lines[][];
	/** vertices translated screen coordinates */
//	protected int x[], y[];

	public Mesh() {
		nVertex = nEdge = 0;
		vertex = null;
		edge = null;
//		lines = null;
//		x = y = null;
	}

	public Mesh(int nV, int nE, Vector3D[] v, int[][] e) {
		nVertex = nV;
		nEdge = nE;
		vertex = v;
		edge = e;
//		x = new int[nVertex];
//		y = new int[nVertex];
//		lines = new int[nEdge][5];		
	}

/* Java 2
	public Mesh(String v, String e) {
		StringTokenizer st;
		String tok;
		ArrayList values;
		double x, y, z;
		int i;
		values = new ArrayList();
		st = new StringTokenizer(v, "[]()<>, \\s");
		while (st.hasMoreTokens()) {
			tok = st.nextToken();
			x = (new Double(tok)).doubleValue();
			tok = st.nextToken();
			y = (new Double(tok)).doubleValue();
			tok = st.nextToken();
			z = (new Double(tok)).doubleValue();
			values.add(new Vector3D(x, y, z));
		}
		nVertex = values.size();
		vertex = new Matrix[nVertex];
		for (i = 0; i < nVertex; i++) {
			vertex[i] = (Matrix) values.get(i);
		}
		values = new ArrayList();
		st = new StringTokenizer(e, "[]()<>, \\s");
		while (st.hasMoreTokens()) {
			tok = st.nextToken();
			values.add(new Integer(tok));
			tok = st.nextToken();
			values.add(new Integer(tok));
		}
		nEdge = values.size() / 2;
		edge = new int[nEdge][2];
		for (i = 0; i < nEdge; i++) {
			edge[i][0] = ((Integer) values.get(i * 2)).intValue();
			edge[i][1] = ((Integer) values.get(i * 2 + 1)).intValue();
		}
//		x = new int[nVertex];
//		y = new int[nVertex];
//		lines = new int[nEdge][5];		
	}
*/
	/**
	 * Creates a new mesh with the transformed vertices and this meshes
	 * edges.
	 */
	public Mesh transform(Matrix trans) {
		if (nVertex == 0)
			return this;
		int i;
		Vector3D[] transVertex = new Vector3D[nVertex];
		for (i = 0; i < nVertex; i++) {
			transVertex[i] = Vector3D.MatrixAsVector3D(trans.mul(vertex[i]));
		}
		return new Mesh(nVertex, nEdge, transVertex, edge);
	}

	/**
	 * Transform this mesh
	 */
	public Mesh transformThis(Matrix trans) {
		if (nVertex == 0)
			return this;
		int i;
		for (i = 0; i < nVertex; i++) {
			vertex[i].transformThis(trans);
		}
		return this;
	}

	/**
	 * Converts the XYZ coordinates of each vertex in flat xy coordinates
	 *  
	 * @param focal focal distance
	 * @param screenX screen dimension x
	 * @param screenY screen dimension y
	 * @return an array of edges quintuplets <x1 y1 x2 y2 (z1+z2)/2>
	 */
	public int[][] wireframe(int focal, int screenX, int screenY) {
		if (nEdge == 0)
			return null;
		int i, x0, y0;
		double z;
		// screen center
		x0 = screenX / 2;
		y0 = screenY / 2;
		/** wireframe lines */
		int lines[][];
		/** vertices translated screen coordinates */
		int x[], y[];
		x = new int[nVertex];
		y = new int[nVertex];
		lines = new int[nEdge][5];
		// Translate vertices to screen coordinates
		for (i = 0; i < nVertex; i++) {
			z = vertex[i].cell[2][0] > 1 ? vertex[i].cell[2][0] : 1;
			x[i] = (int) (x0 + vertex[i].cell[0][0] * focal / z);
			y[i] = (int) (y0 - vertex[i].cell[1][0] * focal / z);
		}
		// Create lines from mesh edges
		for (i = 0; i < nEdge; i++) {
			lines[i][0] = x[edge[i][0]];
			lines[i][1] = y[edge[i][0]];
			lines[i][2] = x[edge[i][1]];
			lines[i][3] = y[edge[i][1]];
			lines[i][4] = ((int) (vertex[edge[i][0]].cell[2][0] + vertex[edge[i][1]].cell[2][0])) >> 1;
		}
		return lines;
	}

}
